﻿// NahidaProject-Thread-BuildExample.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <cassert>
#include <iostream>

#include <EventBus.h>
#include <MemoryPool.h>
#include <SignalAndSlot.h>
#include <ThreadPool.h>

SetEventBusEvent(TestEvent);

class HandlerTest : public NahidaProject::EventBus::EventBusHandler<TestEvent> {
private:
	bool _success;
public:
	HandlerTest() : _success(false) {

	}

	void OnEvent(const TestEvent&) override {
		_success ^= true;
	}

	inline bool isSuccess() const {
		return _success;
	}
};

constexpr float Calculate(float value, int scalar) {
	return value * static_cast<float>(scalar);
}

int main(int argc, char** argv) {
	NahidaProject::EventBus::EventBus eventBus;
	HandlerTest handler;
	TestEvent event;

	eventBus.Subscribe(handler);
	eventBus.Publish(event);

	if (!handler.isSuccess()) {
		std::cerr << "Failed to execute the handler" << std::endl;
	}

	eventBus.Unsubscribe(handler);
	eventBus.Publish(event);
	if (!handler.isSuccess()) {
		std::cerr << "Failed to unsubscribe" << std::endl;
	}

	std::cout << "Executed the handler" << std::endl;

	NahidaProject::MemoryPool pool(32, 10);
	std::cout << pool.PrintFreeBlocks() << std::endl;
	void* ptr1 = pool.Allocate();
	void* ptr2 = pool.Allocate();
	void* ptr3 = pool.Allocate();
	std::cout << pool.PrintFreeBlocks() << std::endl;
	pool.Deallocate(ptr2);
	std::cout << pool.PrintFreeBlocks() << std::endl;
	void* ptr4 = pool.Allocate();
	std::cout << pool.PrintFreeBlocks() << std::endl;

	NahidaProject::Signal<int> signal;
	auto connection = signal.Connect([](int a) {
		std::cout << "Current Number is " << a << std::endl;
		});

	signal(20);
	signal(50);
	connection.Disconnect();

	NahidaProject::ThreadPool::SafeQueue::ThreadPool threadPool{};

	constexpr float num1 = 12.25f;
	constexpr float num2 = 17.75f;
	constexpr int scalar = 2;
	auto foo = threadPool.Enqueue([num1] {
		return num1 * static_cast<float>(scalar);
		});

	auto bar = threadPool.Enqueue(Calculate, num2, scalar);

	const auto result_foo = foo.get();
	const auto result_bar = bar.get();

	std::cout << result_foo << std::endl;
	std::cout << result_bar << std::endl;
	std::cout << result_foo + result_bar << std::endl;

	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
